package com.teaRestaurant.service.Impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageInfo;
import com.teaRestaurant.WebSocket.WebSocketServer;
import com.teaRestaurant.common.utils.SnowFlake;
import com.teaRestaurant.domain.DTO.OrderPageQueryDTO;
import com.teaRestaurant.domain.VO.DayDataVO;
import com.teaRestaurant.domain.entity.Orders;
import com.teaRestaurant.domain.entity.OrderDetail;
import com.teaRestaurant.domain.entity.Tables;
import com.teaRestaurant.mapper.OrderDetailMapper;
import com.teaRestaurant.mapper.OrderMapper;
import com.teaRestaurant.mapper.TableMapper;
import com.teaRestaurant.service.OrderService;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service

public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private TableMapper tableMapper;
    @Autowired
    private WebSocketServer webSocketServer;

    @Override
    public PageInfo<Orders> list(OrderPageQueryDTO orderPageQueryDTO) {
        int pageNum = orderPageQueryDTO.getPageNum();
        int pageSize = orderPageQueryDTO.getPageSize();
        LocalDateTime startTime = orderPageQueryDTO.getStartTime();
        LocalDateTime endTime = orderPageQueryDTO.getEndTime();
        if (startTime != null && endTime != null) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String start = startTime.format(formatter);
            String end = endTime.format(formatter);
            orderPageQueryDTO.setStart(start);
            orderPageQueryDTO.setEnd(end);
        }
        List<Orders> ordersList = orderMapper.list(orderPageQueryDTO);
        // 手搓分页
        List<Orders> ordersList2 = new ArrayList<>();
        for(int i = (pageNum - 1) * pageSize; i< ordersList.size() && i < pageSize * pageNum; i++){
            ordersList2.add(ordersList.get(i));
        }
        PageInfo<Orders> pageInfo = new PageInfo<>(ordersList);
        pageInfo.setList(ordersList2);
        return pageInfo;
    }

    @Override
    @Transactional
    public String insert(Orders orders) {
        // 生成订单号
        SnowFlake snowFlake = new SnowFlake(1,1,1);
        Long num = snowFlake.nextId();
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 设置订单号
        String orderNo = num.toString();
        orders.setOrderNo(orderNo);
        // 插入本地时间
        orders.setOperateTime(now);
        // 设置初始的状态
        orders.setStatus(1);
        // 插入订单
        orderMapper.insertOrder(orders);
        // 插入订单详情
        for (OrderDetail orderDetail : orders.getOrderDetailList()) {
            orderDetail.setOrderNo(orderNo);
            orderDetailMapper.insert(orderDetail);
        }
        // 删除订单时间超过30天的记录
        LocalDateTime thirtyDaysAgo = now.minusDays(30);
        // 查出超过30天的订单号
        List<Long> orderNos = orderMapper.getOrderNos(thirtyDaysAgo);
        delete(orderNos);
        // 发送消息
        Map map = new HashMap<>();
        map.put("type",1);
//        paySuccess();

        // 修改桌面状态和人数
        Tables table = new Tables();
        table.setStatus(2);
        table.setNumber(orders.getTableNumber());
        LambdaQueryWrapper<Tables> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Tables::getId , orders.getTableId());
        tableMapper.update(table,wrapper);
        return orderNo;
    }

    @Override
    @Transactional
    public void delete(List<Long> orderNos) {
        for(Long orderNo: orderNos) {
            // 1、删除套餐详情
            LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OrderDetail::getOrderNo,orderNo);
            orderDetailMapper.delete(wrapper);
            // 2、删除套餐
            orderMapper.deleteById(orderNo);
        }
    }

    @Override
    public void update(Orders orders) {
        // 修改状态
        LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Orders::getOrderNo, orders.getOrderNo());
        orderMapper.update(orders,wrapper);
    }

    @Override
    public Orders getById(String orderNo) {
        return orderMapper.getById(orderNo);
    }

    @Override
    public DayDataVO getDayData() {
        //获得当天的开始时间
        LocalDateTime begin = LocalDateTime.now().with(LocalTime.MIN);
        //获得当天的结束时间
        LocalDateTime end = LocalDateTime.now().with(LocalTime.MAX);
        DayDataVO dayData = getDayData(begin, end);
        return dayData;
    }

    @Override
    public void exportBusinessData(HttpServletResponse response) throws IOException {
        // 查询月数据
        LocalDateTime dateBegin = LocalDateTime.now().minusDays(30).with(LocalTime.MIN);
        LocalDateTime dateEnd = LocalDateTime.now().minusDays(0).with(LocalTime.MAX);
        DayDataVO monthData = getDayData(dateBegin,dateEnd);
        InputStream in =null;
        XSSFWorkbook excel =null;
        ServletOutputStream out=null;

        try{
            // 2.通过POI将数据写入到Excel文件中
            //创建输入流
            in = this.getClass().getClassLoader().getResourceAsStream("templates/运营数据报表模板.xlsx");

            // 基于模块文件创建一个新的excel文件
             excel = new XSSFWorkbook(in);

            XSSFSheet sheet = excel.getSheet("Sheet1");
            // 填充数据--时间
            sheet.getRow(1).getCell(1).setCellValue("时间：" + dateBegin.toString().substring(0,10) + "至" + dateEnd.toString().substring(0,10));

            // 获得第4行
            XSSFRow row = sheet.getRow(3);
            row.getCell(2).setCellValue(monthData.getTurnover());
            row.getCell(4).setCellValue(monthData.getOrderCount());
            row.getCell(6).setCellValue(monthData.getUsedOrderCount());

            // 获取第5行
            row = sheet.getRow(4);
            row.getCell(2).setCellValue(monthData.getAvgOrderMoney());

            // 填充明细数据
            for (int i = 0; i < 30; i++) {
                LocalDateTime now = dateBegin.plusDays(i);
                LocalDateTime begin = LocalDateTime.now().minusDays(i).with(LocalTime.MIN);
                LocalDateTime end = LocalDateTime.now().minusDays(i).with(LocalTime.MAX);
                // 查询某一天的数据
                DayDataVO dayData = getDayData(begin, end);
                System.out.println(dayData);
                // 获取某一行
                row = sheet.getRow(7 + i);
                row.getCell(1).setCellValue(now.toString().toString().substring(0,10));
                row.getCell(2).setCellValue(dayData.getTurnover());
                row.getCell(3).setCellValue(dayData.getUsedOrderCount());
                double percent = 0;
                if (dayData.getOrderCount() != 0){
                    // 订单完成百分比
                    percent = dayData.getUsedOrderCount() / dayData.getOrderCount();
                    //保留俩位小数
                    percent = (double) Math.round(percent);
                }
                row.getCell(4).setCellValue(percent);
                row.getCell(5).setCellValue(dayData.getAvgOrderMoney());
                System.out.println(row.getCell(2));
            }
            // 设置响应头，告诉浏览器这是一个文件下载
            String fileName = new String("运营数据报表.xlsx".getBytes("UTF-8"), "ISO-8859-1");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");


            // 3.通过输出流将Excel文件下载到客户端
             out = response.getOutputStream();
            excel.write(out);

            out.flush();
        }catch (IOException e) {
            e.printStackTrace();
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            // 可以选择返回错误信息
            response.getWriter().write("Error generating Excel file");
        }finally {

            // 关闭资源
            if (excel != null) {
                excel.close();
            }
            if (in != null) {
                in.close();
            }
        }
    }

    @Override
    public void updateStatus(String orderNo, Integer status) {
        System.out.println("订单更新状态");
        System.out.println(orderNo);
        System.out.println(status);

        orderMapper.updateStatus(orderNo,status);
    }

    @Override
    public void voice() {
        Map map = new HashMap<>();
        map.put("type",1);
        String json = JSON.toJSONString(map);
        webSocketServer.sendToAllClient(json);
    }


    public DayDataVO getDayData(LocalDateTime begin, LocalDateTime end) {
        // 营业额
        Double turnover = orderMapper.getTurnover(begin,end);
        turnover = turnover == null?0:turnover;
        // 订单数量
        Integer orderCount = orderMapper.getOrderCount (begin,end,0);
        // 有效订单数
        Integer usedOrderCount = orderMapper.getOrderCount (begin,end,2);
        // 订单平均价
        Double avgOrderMoney = orderMapper.getAvgOrderMoney(begin,end);
        avgOrderMoney = avgOrderMoney == null?0:avgOrderMoney;
        return DayDataVO.builder()
                .turnover(turnover)
                .orderCount(orderCount)
                .usedOrderCount(usedOrderCount)
                .avgOrderMoney(avgOrderMoney)
                .build();
    }
}
